home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
SMISC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-07
|
19KB
|
870 lines
/* Miscellaneous Internet servers: discard, echo and remote
* Copyright 1991 Phil Karn, KA9Q
*/
#include "global.h"
#include "commands.h"
#ifndef MSDOS
#include <time.h>
#endif
#include "netuser.h"
#include "remote.h"
#include "smtp.h"
#include "tcp.h"
#include "nr4.h"
#include "mailbox.h"
#include "stats.h"
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: smisc.c,v 1.31 1997/09/07 21:18:28 root Exp root $";
#endif
char const *Rempass = ""; /* Remote access password */
char const *RemRTpass = ""; /* Remote access password for adding routes */
extern char *MMotd;
#ifdef ALLSERV
static void discserv (int s, void *unused, void *p);
static void echoserv (int s, void *unused, void *p);
static void quoteserv (int s, void *unused, void *p);
static void timeserv (int s, void *unused, void *p);
static void daytimeserv (int s, void *unused, void *p);
static void handleserver (int s, const char *name, int type);
#endif
static int chkrpass (struct mbuf * bp, int isaxip);
#ifdef TRACESERVER
static void traceserv (int s, void *unused, void *p);
#endif
#ifdef ALLSERV
char *getquote (void);
#endif
#ifdef TUTOR
static void tutorserver (int s, void *mode, void *p);
#endif
static const char deletenone[] = "The server is not active - nothing to stop!\n";
static const char openstr[] = "open %s";
static const char quotehdr[] = "\nQuote-of-the-Day at '%s' on %s\n";
static const char failedstr[] = "%s failed";
static const char closestr[] = "close %s";
static const char discardlistener[] = "Discard listener";
static const char discardserver[] = "Discard server";
static const char discardstr[] = "discard";
static const char timelistener[] = "Time listener";
static const char timeserver[] = "Time server";
static const char timestr[] = "time";
static const char daytimelistener[] = "Daytime listener";
static const char daytimeserver[] = "Daytime server";
static const char daytimestr[] = "daytime";
static const char echolistener[] = "Echo listener";
static const char echoserver[] = "Echo server";
static const char echostr[] = "echo";
static const char tracelistener[] = "Trace listener";
static const char traceserver[] = "Trace server";
static const char opentrace[] = "open trace";
static const char remotelistener[] = "Remote listener";
static const char passwdfail[] = "PASSWORD FAIL";
static const char remoteexit[] = "Remote exit %s %s";
static const char remotekick[] = "Remote kick by %s for host %s";
static const char remoteroute[] = "Remote route %s attempt from %s for '%s' %s";
static const char quotelistener[] = "Quote listener";
static const char quoteserver[] = "Quote server";
static const char quotestr[] = "quote";
static const char noopen[] = "Couldn't open '%s'\n";
static const char telnetstr[] = "telnet";
#ifdef MSDOS
static const char remotereset[] = "Remote reset %s %s";
#endif
#ifdef RLOGINSERV
static const char RLoginlistener[] = "RLogin listener";
static const char RLoginserver[] = "RLogin server";
#endif
#ifdef TUTOR
static const char tutopen[] = "open %s server";
static const char nonamestr[] = "noname";
static const char tutclose[] = "close %s server";
static const char tutorlistener[] = "Tutor listener";
static const char Tutorserver[] = "Tutor server";
static const char infolistener[] = "Info listener";
static const char Infoserver[] = "Info server";
static const char newslistener[] = "News listener";
static const char Newsserver[] = "News server";
#endif
static int Rem = -1;
void
server_disconnect_io (void)
{
if (Curproc->input != -1) {
close_s (Curproc->input);
Curproc->input = -1;
}
if (Curproc->output != -1) {
close_s (Curproc->output);
Curproc->output = -1;
}
}
int
deleteserver (int *mysocket)
{
if (*mysocket != -1) {
close_s (*mysocket);
*mysocket = -1;
} else
tputs (deletenone);
return 0;
}
/* Start up a TCP server */
int
installserver (
int argc,
char *argv[],
int *mysocket,
const char *listener,
int defport,
uint32 defaddress,
const char *procname,
void (*proc) (int, void *, void *),
unsigned int size,
void *parm
) {
struct sockaddr_in lsocket;
int s;
if (*mysocket != -1)
return 0;
ksignal (Curproc, 0); /* Don't keep the parser waiting */
chname (Curproc, listener);
lsocket.sin_family = AF_INET;
lsocket.sin_addr.s_addr = defaddress;
if (argc < 2)
lsocket.sin_port = (int16) defport;
else
lsocket.sin_port = (int16) atoi (argv[1]);
*mysocket = socket (AF_INET, SOCK_STREAM, 0);
(void) bind (*mysocket, (char *) &lsocket, sizeof (lsocket));
(void) listen (*mysocket, 1);
server_disconnect_io ();
for (;;) {
if ((s = accept (*mysocket, NULLCHAR, (int *) NULL)) == -1)
break; /* Service is shutting down */
/* Low mem check now done in tcpin.c - WG7J */
/* Spawn a server */
(void) newproc (procname, (unsigned int) size, proc, s, parm, NULL, 0);
}
return 0;
}
#ifdef RLOGINSERV
static int Srlogin = -1;
#endif
#ifdef TRACESERVER
static int Strace = -1;
#endif
#ifdef TUTOR
int Stutor = -1;
int Sinfo = -1;
int Snews = -1;
#endif
#ifdef ALLSERV
static int Sdisc = -1;
static int Stime = -1;
static int Squote = -1;
static int Sdaytime = -1;
static int Secho = -1;
#define DIFFTIME 2208988800LU
#define T_TIME 0
#define T_DAYTIME 1
#define T_DISCARD 2
#define T_ECHO 3
#define T_QUOTE 4
static void
handleserver (int s, const char *name, int type)
{
struct mbuf *bp;
time_t currtime;
char buf[32];
long adjust;
struct tm *tmp;
(void) sockowner (s, Curproc);
sprintf (buf, openstr, name);
log (s, buf);
switch (type) {
case T_DISCARD:
while (recv_mbuf (s, &bp, 0, NULLCHAR, NULL) > 0)
free_p (bp);
break;
case T_QUOTE:
{
char buf2[512], *cp;
cp = getquote ();
currtime = time (&currtime);
sprintf (buf2, quotehdr, Hostname, ctime (&currtime));
bp = qdata ((unsigned char *) buf2, (int16) strlen (buf2));
(void) send_mbuf (s, bp, 0, NULLCHAR, 0);
bp = qdata ((unsigned char *) cp, (int16) strlen (cp));
free (cp);
}
goto common;
case T_TIME:
case T_DAYTIME:
currtime = time (&currtime);
tmp = localtime (&currtime);
if (type == T_DAYTIME) { /* daytime protocol */
(void) strftime (buf, 32, "%a %b %d, %Y %X %Z\n", tmp);
bp = qdata ((unsigned char *) buf, (int16) strlen(buf));
} else {
/*
* Change 1970 start time to 1900 start time,
* and put it in network order
*/
#if defined(HAVE_TM_ISDST) && !defined(MSDOS)
adjust = (timezone - (tmp->tm_isdst * 3600L)) / -1L;
#else
adjust = tmp->tm_gmtoff;
#endif
(void) put32 ((unsigned char *) buf, (uint32) (((uint32)currtime + DIFFTIME) + adjust)); /*lint !e737 */
/* enqueue for transmission */
bp = qdata ((unsigned char *) buf, sizeof (int32));
}
common:
if (send_mbuf (s, bp, 0, NULLCHAR, 0) == -1) {
sprintf (buf, failedstr, name);
log (s, buf);
}
break;
case T_ECHO:
while (recv_mbuf (s, &bp, 0, NULLCHAR, NULL) > 0)
(void) send_mbuf (s, bp, 0, NULLCHAR, 0);
break;
default:
break;
}
sprintf (buf, closestr, name);
log (s, buf);
close_s (s);
}
/* Start up TCP discard server */
int
dis1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Sdisc, discardlistener, IPPORT_DISCARD,
INADDR_ANY, discardserver, discserv, 576, NULL));
}
static void
discserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
#ifdef STATS_USE
STATS_adduse (1);
MiscUsers++;
#endif
handleserver (s, discardstr, T_DISCARD);
#ifdef STATS_USE
MiscUsers--;
#endif
}
/* Stop discard server */
int
dis0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Sdisc));
}
/* Start up TCP time server */
int
time1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Stime, timelistener, IPPORT_TIME,
INADDR_ANY, timeserver, timeserv, 512, NULL));
}
static void
timeserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
(void) sockmode (s, SOCK_BINARY);
handleserver (s, timestr, T_TIME);
}
/* Stop time server */
int
time0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Stime));
}
/* Start up TCP daytime server */
int
daytime1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Sdaytime, daytimelistener, IPPORT_DAYTIME,
INADDR_ANY, daytimeserver, daytimeserv, 576, NULL));
}
static void
daytimeserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
handleserver (s, daytimestr, T_DAYTIME);
}
/* Stop time server */
int
daytime0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Sdaytime));
}
/* Start up TCP echo server */
int
echo1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Secho, echolistener, IPPORT_ECHO,
INADDR_ANY, echoserver, echoserv, 2048, NULL));
}
static void
echoserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
#ifdef STATS_USE
STATS_adduse (1);
MiscUsers++;
#endif
handleserver (s, echostr, T_ECHO);
#ifdef STATS_USE
MiscUsers--;
#endif
}
/* stop echo server */
int
echo0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Secho));
}
#endif /*ALLSERV*/
#if defined(TRACESERVER) || defined(ENCAP)
extern struct cmds Cmds[];
#endif
#ifdef TRACESERVER
/* Start up TCP trace server */
int
trace1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Strace, tracelistener, IPPORT_TRACE,
INADDR_ANY, traceserver, traceserv, 1024, NULL));
}
/* Stop trace server */
int
trace0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Strace));
}
static void
traceserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
#define CMDLINE 80
char *cmd;
int outsave, insave;
#ifdef STATS_USE
STATS_adduse (1);
MiscUsers++;
#endif
(void) sockowner (s, Curproc);
log (s, opentrace);
outsave = Curproc->output;
Curproc->output = s;
insave = Curproc->input;
Curproc->input = s;
/* allocate the command buffer */
cmd = mallocw (CMDLINE + 1);
while (recvline (s, (unsigned char *) cmd, CMDLINE) > 0) {
if (!strnicmp ("tr", cmd, 2)) /* only allow 'trace' command ! */
(void) cmdparse (Cmds, cmd, NULL);
if (!strnicmp ("ex", cmd, 2))
break;
}
removetrace ();
Curproc->input = insave;
Curproc->output = outsave;
log (s, "close trace");
#ifdef STATS_USE
MiscUsers--;
#endif
close_s (s);
}
#endif /* TRACESERVER */
/* Start remote exit/reboot server */
int
rem1 (int argc, char *argv[], void *p OPTIONAL)
{
struct sockaddr_in lsocket, fsock;
int i;
int command;
struct mbuf *bp, **bpp;
uint32 addr;
char temp[80], cmdbuf[128];
int len;
int action;
char *ab, *cp;
int badaddr;
if (Rem != -1)
return 0;
ksignal (Curproc, 0);
chname (Curproc, remotelistener);
server_disconnect_io ();
lsocket.sin_family = AF_INET;
lsocket.sin_addr.s_addr = INADDR_ANY;
if (argc < 2)
lsocket.sin_port = IPPORT_REMOTE;
else
lsocket.sin_port = (int16) atoi (argv[1]);
Rem = socket (AF_INET, SOCK_DGRAM, 0);
(void) bind (Rem, (char *) &lsocket, sizeof (lsocket));
for (;;) {
i = sizeof (fsock);
if (recv_mbuf (Rem, &bp, 0, (char *) &fsock, &i) == -1)
break;
bpp = &bp;
command = PULLCHAR (bpp);
switch (command) {
#ifdef MSDOS /* Only present on PCs running MSDOS */
case SYS_RESET:
i = chkrpass (bp, 0);
log (Rem, remotereset, psocket ((struct sockaddr *) &fsock),
i == 0 ? passwdfail : "");
if (i != 0) {
/*Indicate a hardware reset*/
where_outta_here (2, "rem1");
}
break;
#endif
case SYS_EXIT:
i = chkrpass (bp, 0);
log (Rem, remoteexit, psocket ((struct sockaddr *) &fsock), (i == 0) ? passwdfail : "");
if (i != 0) /*No reset*/
where_outta_here (0, "rem1");
break;
case KICK_ME:
if (len_p (bp) >= sizeof (int32))
addr = pull32 (&bp);
else
addr = fsock.sin_addr.s_addr;
/* get round strange printf bug */
strncpy (temp, inet_ntoa (addr), 20);
log (Rem, remotekick, psocket ((struct sockaddr *) &fsock), temp);
#ifdef NETROM
donodetick (); /* g3rra's idea!..hmmm */
#endif /* NETROM */
(void) kick (addr);
smtptick ((void *) addr);
break;
#ifdef ENCAP
case ROUTE_ADD:
case ROUTE_DROP:
action = (command == ROUTE_ADD) ? 1 : 0;
/* first, extract the route string */
len = PULLCHAR (bpp); /* get the length of the name portion */
if (len > 18)
break;
(void) pullup (bpp, (unsigned char *) temp, (int16) len);
temp[len] = 0;
/* now check the password */
i = chkrpass (bp, 1);
ab = psocket ((struct sockaddr *) &fsock);
if ((cp = strchr (ab, ':')) != NULLCHAR)
*cp = 0;
badaddr = (strcmp (ab, "127.0.0.1")) ? 0 : 1;
if (badaddr && action)
tcmdprintf ("Attempt to add remote route to 127.0.0.1 - ignored\n");
log (Rem, remoteroute, (action) ? "add" : "drop", ab, temp, (badaddr) ? "cannot route to 127.0.0.1" : (i == 0) ? passwdfail : "");
if (strncmp (temp, "44.", 3) || !strncmp (ab, "44.", 3) || aton(temp) == 0)
i = 0; /* disable if route not for amprnet or from amprnet (error) */
if (i != 0) {
/* add/drop the route */
if (action)
sprintf (cmdbuf, "route addp %s encap %s", temp, ab);
else
sprintf (cmdbuf, "route drop %s", temp);
(void) cmdparse (Cmds, cmdbuf, NULL);
}
break;
#endif
default:
break;
}
#if 0 /* deliberate memory leak */
free_p (bp);
#endif
}
close_s (Rem);
Rem = -1;
return 0;
}
/* Check remote password */
static int
chkrpass (struct mbuf *bp, int isaxip)
{
char *lbuf;
int16 len;
int rval = 0;
len = len_p (bp);
if (!isaxip) {
if (strlen (Rempass) == 0 || strlen (Rempass) != len)
return rval;
} else {
if (strlen (RemRTpass) == 0 || strlen (RemRTpass) != len)
return rval;
}
lbuf = mallocw (len);
(void) pullup (&bp, (unsigned char *) lbuf, len);
if (strncmp ((!isaxip) ? Rempass : RemRTpass, lbuf, len) == 0)
rval = 1;
free (lbuf);
return rval;
}
int
rem0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
close_s (Rem);
return 0;
}
#ifdef ALLSERV
/* Start up TCP quote server */
int
quote1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Squote, quotelistener, IPPORT_QUOTE,
INADDR_ANY, quoteserver, quoteserv, 1536, NULL));
}
static void
quoteserv (int s, void *unused OPTIONAL, void *p OPTIONAL)
{
handleserver (s, quotestr, T_QUOTE);
}
/* Stop quote server */
int
quote0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Squote));
}
char *
getquote ()
{
char buf2[512];
char searchstr[8];
char buf3[4096];
char *cptr;
FILE *fp;
struct date dt;
if (Squote == -1)
return (NULLCHAR);
if ((fp = fopen (Quotes, READ_TEXT)) == NULLFILE) {
if (MMotd != NULLCHAR)
return (strdup (MMotd));
else
return (NULLCHAR);
}
tnos_getdate (&dt);
sprintf (searchstr, "[%-d]", dt.da_day);
while (fgets (buf2, 512, fp) != NULLCHAR) {
if (!strncmp (searchstr, buf2, strlen (searchstr)))
break;
}
buf3[0] = 0;
if ((cptr = strchr (buf2, '%')) != NULLCHAR) {
rip (buf2);
(void) fclose (fp);
if ((fp = fopen (++cptr, READ_TEXT)) == NULLFILE) {
tcmdprintf (noopen, &buf2[1]);
return (NULLCHAR);
}
}
while (fgets (buf2, 512, fp) != NULLCHAR) {
if (*buf2 == '[')
break;
strcat (buf3, buf2);
}
(void) fclose (fp);
return (strdup (buf3));
}
#endif /* ALLSERV */
/* Execute user quote command */
int
doquote (int argc OPTIONAL, char *argv[], void *p)
{
free (argv[0]);
argv[0] = strdup (telnetstr);
if (argv[2])
free (argv[2]);
argv[2] = strdup ("17");
if (!argv[1])
argv[1] = strdup (Hostname);
return dotelnet (3, argv, p);
}
#ifdef RLOGINSERV
/* Start up RLOGIN server */
int
rlogin1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Srlogin, RLoginlistener, IPPORT_RLOGIN,
INADDR_ANY, RLoginserver, pbbs_incom, 2048, (void *) RLOGIN_LINK));
}
/* Stop RLOGIN server */
int
rlogin0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Srlogin));
}
#endif
#ifdef TUTOR
extern void tutorserv (const char *, struct mbx *, int, int, int);
static const char *tut[] = {"tutor", "info", "news"};
static void
tutorserver (int s, void *mode, void *p OPTIONAL)
{
int outsave, insave;
(void) sockmode (s, SOCK_ASCII);
(void) sockowner (s, Curproc);
log (s, tutopen, tut[(int) mode]);
outsave = Curproc->output;
Curproc->output = s;
insave = Curproc->input;
Curproc->input = s;
tutorserv (nonamestr, NULLMBX, (int) mode, 0, 1);
Curproc->input = insave;
Curproc->output = outsave;
log (s, tutclose, tut[(int) mode]);
close_s (s);
}
/* Start up TCP tutorial server */
int
tutor1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Stutor, tutorlistener, IPPORT_TUTOR,
INADDR_ANY, Tutorserver, tutorserver, 2048, (void *) 0));
}
/* Stop tutorial server */
int
tutor0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Stutor));
}
/* Start up TCP tutorial server */
int
info1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Sinfo, infolistener, IPPORT_INFO,
INADDR_ANY, Infoserver, tutorserver, 2048, (void *) 1));
}
/* Stop tutorial server */
int
info0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Sinfo));
}
/* Start up TCP news server */
int
news1 (int argc, char *argv[], void *p OPTIONAL)
{
return (installserver (argc, argv, &Snews, newslistener, IPPORT_NEWS,
INADDR_ANY, Newsserver, tutorserver, 2048, (void *) 2));
}
/* Stop news server */
int
news0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
{
return (deleteserver (&Snews));
}
static char WhichTutor = 0;
/* Execute user tutor command */
int
dotutor (int argc OPTIONAL, char *argv[], void *p)
{
char buf[6];
int i = WhichTutor;
WhichTutor = 0;
free (argv[0]);
argv[0] = strdup (telnetstr);
if (argv[2])
free (argv[2]);
sprintf (buf, "%-d", IPPORT_TUTOR - i);
argv[2] = strdup (buf);
if (!argv[1])
argv[1] = strdup (Hostname);
return dotelnet (3, argv, p);
}
/* Execute user info command */
int
doinfo (int argc, char *argv[], void *p)
{
WhichTutor = 1;
return (dotutor (argc, argv, p));
}
/* Execute user info command */
int
donews (int argc, char *argv[], void *p)
{
WhichTutor = 2;
return (dotutor (argc, argv, p));
}
#endif